<?php
/**
 * 抽奖活动
 * User: cxm
 * Date: 2020/9/25
 * Time: 9:14
 */
namespace App\Http\Controllers\Home;
use App\Models\Activity;
use App\Models\ActivityExtend;
use App\Models\Advise;
use App\Models\AwardGoods;
use App\Models\AwardGoodsClass;
use App\Models\AwardHistory;
use App\Models\Order;
use App\Models\Region;
use App\Models\SystemConfig;
use App\Models\User;
use App\Models\UserDrawRecord;
use App\Models\UserHelpRecord;
use App\Models\UserShare;
use App\Models\UserStepRecord;
use App\Models\UserWeixin;
use Carbon\Carbon;
use EasyWeChat\Factory;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redis;

class ActivityController extends Controller {
    /**
     * 获取获取的奖品列表
     * URL POST:/api/home/activity/userGetDraw
     * @param Request $request
     * @param int activity_id 活动ID
     * @param int page 页码
     * @param int limit 每页显示条数
     * @return mixed
     */
    public function userGetDraw(Request $request){
        $params = $request->only(['activity_id','page','limit']);
        if (!array_key_exists('activity_id',$params) || empty($params['activity_id'])) {
            return $this->error('缺少活动ID');
        }
        $params['limit'] = 1000;
        $user = $this->userModel();
        $params['where'][] = ['user_id',$user['id']];
        // 未领取的
        $params['where'][] = ['status',2];
        $params['where'][] = ['activity_id',$params['activity_id']];
        $params['with'][] = ['goods'=>function($query){
            $query->select('id','name','type','is_get')
                ->with('goods:id,award_goods_id,name,img,stock,un_stock');
        }];
        $data = AwardHistory::listByWhere($params);
        return $this->success('查询成功',$data);
    }

    /**
     * 活动列表
     * URL POST:/api/home/activity/getLists
     * @param Request $request
     * @param int page 页码
     * @param int limit 每页显示条数
     * @return mixed
     */
    public function getList(Request $request){
        $params = $request->only(['page','limit']);
        $params['orderBy'] = ['sort asc','created_at desc'];
        // 图片
        $params['with'][] = 'file:id,path';
        $data = Activity::listByWhere($params);
        return $this->success('查询成功',$data);
    }

    /**
     * 活动详情
     * URL POST:/api/home/activity/detail
     * @param Request $request
     * @param int activity_id 活动ID
     * @return mixed
     */
    public function activityDetail(Request $request){
        $params = $request->only(['activity_id']);
        if (!array_key_exists('activity_id',$params) || empty($params['activity_id'])) {
            return $this->error('缺少活动ID');
        }
        $user = $this->userModel();
        $params['where'][] = ['id',$params['activity_id']];
        // 活动详情
        $params['with'][] = 'file:id,path';
        $activity = Activity::detailsWith($params);
        // 用户中奖记录
        $draw_history = AwardHistory::getUserDraw($user['id'],$params['activity_id']);
        // 活动人数
        $people_num = User::whereNotNull('sign_time')->count();
        $data = [
            'activity'      => $activity,
            'draw_history'  => $draw_history,
            'people_num'    => $people_num
        ];
        return $this->success('查询成功',$data);
    }

    /**
     * 活动奖品列表
     * URL POST:/api/home/activity/goodsLists
     * @param Request $request
     * @param int activity_id 活动ID
     * @param int page 页码
     * @param int limit 每页显示条数
     * @return mixed
     */
    public function goodsLists(Request $request){
        $params = $request->only(['activity_id','page','limit']);
        if (!array_key_exists('activity_id',$params) || empty($params['activity_id'])) {
            return $this->error('缺少活动ID');
        }
        $params['where'][] = ['is_show',1];
        $params['where'][] = ['activity_id',$params['activity_id']];
        $params['orderBy'] = ['sort asc','created_at desc'];
        // 图片
        $params['with'][] = 'file:id,path';
        $params['with'][] = 'goods';
        $params['field'] = ['id','type','img','name','short_name','describe','is_get'];
        $result = AwardGoods::listByWhere($params);
        return $this->success('查询成功',$result);
    }

    /**
     * 商品详情
     * URL POST:/api/home/activity/goodsDetail
     * @param Request $request
     * @param int goods_id 商品ID
     * @return mixed
     */
    public function goodsDetail(Request $request){
        $params = $request->only(['goods_id']);
        if (!array_key_exists('goods_id',$params) || empty($params['goods_id'])) {
            return $this->error('缺少商品ID');
        }
        $params['where'][] = ['id',$params['goods_id']];
        // 图片
        $params['with'][] = 'file:id,path';
        $goods = AwardGoods::detailsWith($params);
        return $this->success('查询成功',$goods);
    }

    /**
     * 用户抽奖次数
     * URL POST:/api/home/activity/userDrawNum
     * @param Request $request
     * @param int activity_id 活动ID
     * @return mixed
     */
    public function userDrawNum(Request $request){
        $params = $request->only(['activity_id']);
        if (!array_key_exists('activity_id',$params) || empty($params['activity_id'])) {
            return $this->error('缺少活动ID');
        }
        $user = $this->userModel();

        // 1、用户是否报名
        if (!$user->sign_time) {
            return $this->error('你还没有报名，不能参加活动');
        }

        $activity = Activity::find($params['activity_id']);
        if (!$activity) {
            return $this->error('活动不存在');
        }
        // 判断活动是否结束
        if (!empty($activity['start_time']) && time() < strtotime($activity['start_time'])) {
            return $this->error('活动还没有开始，请耐心等待……');
        }
        if (!empty($activity['end_time']) && time() > strtotime($activity['end_time'])) {
            return $this->error('活动已结束，您来晚了…………');
        }

        // 2、用户当前的步数
        $userStep = UserStepRecord::getUserStep($user['id']);
        if (!$userStep) {
            return $this->error('请前往首页，获取运动步数再返回抽奖');
        }
        // 系统设置最低步数
        $systemStep = SystemConfig::getSingleValue('start_step');
        if ($userStep < $systemStep) {
            return $this->error('抱歉，您还没有达到最低步数'.$systemStep.',不能参与抽奖',4002);
        }
        // 3、 用户是否已中奖
        $prize_info = AwardHistory::userPrizeInfo($user['id'],$params['activity_id']);
        if ($prize_info) {
            return $this->error('抱歉，您的抽奖次数用完了',4003);
        }
        // 查看当天用户是否参与抽奖
        $day_in = AwardHistory::userDayPartake($user['id'],$params['activity_id']);
        if ($day_in) {
            return $this->error('您今天的抽奖次数用完了，请明天在来');
        }
        return $this->success('可以抽奖');
    }

    /**
     * 用户信息
     * URL POST:/api/home/activity/userInfo
     * @param Request $request
     * @return mixed
     */
    public function userInfo(Request $request){
        $user = $this->userModel();
        return $this->success('查询成功',$user);
    }

    /**
     * 工卡号是否正确
     * URL POST:/api/home/activity/cardNoIsRight
     * @param Request $request
     * @param string name 名称
     * @param string mobile 手机
     * @param string card_no 工卡号
     * @return mixed
     */
    public function cardNoIsRight(Request $request){
        $params = $request->only(['name','mobile','card_no']);
        $user = $this->userModel();
        $validator = Validator::make($params,[
            'name'          => ['required'],
            'mobile'        => ['required','regex:/^1[3456789]\d{9}$/'],
            'card_no'       => ['required']
        ],[
            'name.required'         => '用户名称是必须的',
            'mobile.required'       => '用户手机是必须的',
            'mobile.regex'          => '手机格式错误',
            'card_no.required'      => '工会服务卡号是必须的',
        ]);
        if ($validator->fails()) {
            return $this->error($validator->errors()->first());
        }
        if ($user->is_check == 1) {
            return $this->error('您已经匹配过了，请勿重新匹配');
        }
        $where = [];
        //$where[] = ['name',$params['name']];
        //$where[] = ['mobile',$params['mobile']];
        $where[] = ['card_no',$params['card_no']];
        $res = User::detail($where);
        if (!$res) {
            return $this->error('工会服务卡号不匹配');
        }
        //$names = rtrim($params['name'],',');
        if ($res['name'] != $params['name']) {
            return $this->error("名称与工会服务卡号的名称不配。你输入的名称为：".$params['name']);
        }
        // 修改卡号匹配状态
        $result = User::where(['card_no'=>$params['card_no']])->update([
            'is_check'  => 1,
            'name'      => $params['name'],
            'mobile'    => $params['mobile'],
            'sign_time' => Carbon::now()
        ]);
        if ($result === false) {
            return $this->error('修改用户信息失败');
        }
        $data = [
            'user'  => $res
        ];
        // 判断匹配的用户和当前登录的用户是否一个，不同则返回新的token
        if ($res['id'] != $user['id']) {
            // 更改微信绑定的用户
            UserWeixin::where('user_id',$user['id'])->update(['user_id'=>$res['id']]);
            // 删除报名时的用户 未输入卡号的情况
            User::where([
                'id'      => $user['id']
            ])->forceDelete();
            $token =  auth('api')->tokenById($res['id']);
            $data['token'] = $token;
        }
        return $this->success('查询成功',$data);
    }

    /**
     * 开始抽奖
     * URL POST:/api/home/activity/run
     * @param Request $request
     * @param int activity_id 活动ID
     * @return mixed
     * @throws
     */
    public function luckDraw(Request $request){
        $params = $request->only(['activity_id']);
        if (!array_key_exists('activity_id',$params) || empty($params['activity_id'])) {
            return $this->error('缺少活动ID');
        }
        $activity = Activity::find($params['activity_id']);
        if (!$activity) {
            return $this->error('活动不存在');
        }
        // 判断活动是否结束
        if (!empty($activity['start_time']) && time() < strtotime($activity['start_time'])) {
            return $this->error('活动还没有开始，请耐心等待……');
        }
        if (!empty($activity['end_time']) && time() > strtotime($activity['end_time'])) {
            return $this->error('活动已结束，您来晚了…………');
        }
        $user = $this->userModel();
        // 活动ID
        $activity_id = $params['activity_id'];
        // 查看用户是否可以抽奖
        // 1、用户是否报名
        if (!$user->sign_time) {
            return $this->error('你还没有报名，不能参加活动');
        }
        if ($params['activity_id'] == 1) {
            // 2、用户当前的步数
            $userStep = UserStepRecord::getUserStep($user['id']);
            // 系统设置最低步数
            $systemStep = SystemConfig::getSingleValue('start_step');
            if ($userStep < $systemStep) {
                return $this->error('抱歉，您还没有达到最低步数'.$systemStep.',不能参与抽奖');
            }
        }

        // 3、 用户是否已中奖
        $prize_info = AwardHistory::userPrizeInfo($user['id'],$activity_id);
        if ($prize_info) {
            return $this->error('抱歉，您已经中过奖了，不能继续抽奖…………');
        }

        // 查看当天用户是否参与抽奖
        $day_in = AwardHistory::userDayPartake($user['id'],$params['activity_id']);
        if ($day_in) {
            return $this->error('您今天的抽奖次数用完了，请明天在来');
        }

        // 查询所有的奖品
        $prize_arr =  AwardGoods::getGoodsLists($activity_id);
        $goods = $prize_arr;
        // 重组数据 计算奖品剩余数量
        foreach ($goods as &$prize){
            //如果无库存，则抽中此奖品的概率为0
            if($prize['un_stock'] <= 0){
                $prize['probability'] = 0;
            }
        }

        // 查看是否还有奖品
        $remain_stock = array_sum(array_column($prize_arr,'un_stock'));

        if($remain_stock <= 0){
            Activity::end($activity_id);
            return $this->error('奖品已抽取完，活动结束');
        }

        /**
         * 奖项数组
         * 是一个二维数组，记录了所有本次抽奖的奖项信息，
         * 其中key表示中奖等级,val表示中奖概率。
         * 注意其中的val必须为整数，你可以将对应的 奖项的val设置成0，即意味着该奖项抽中的几率是0，
         * 数组中val的总和（基数），基数越大越能体现概率的准确性。
         * 本例中val的总和为100，那么中奖概率就是1%，
         * 如果val的总和是10000，那中奖概率就是万分之一了。
         */
        $arr = $draw_num = [];
        foreach ($prize_arr as $key=>&$val){
            $arr[$val['id']] = $val['un_stock'] > 0 ? $val['probability'] : 0; // 中奖几率
            $draw_num[$val['id']] = $val['max_num'];// 必中次数 例如：1000次必中
        }
        // 中奖率最大值
        $max_num = max($arr);
        if ($max_num > 0) {
            // 用户中奖ID
            $rid = $this->userDrawGoods($arr,$draw_num,$user['id'],$activity_id);
        }else{
            $rid = AwardGoods::getThanksId($activity_id); // 谢谢参与的ID
        }

//

        $data=[];
        foreach ($prize_arr as $kid=>$v){
            if($v['id']==$rid){
                unset($v['un_stock']);
                unset($v['probability']);
                $data=$v;
            }
        }
        //所有参数
        $json_data['goods'] = $goods; //活动奖品
        $history_id = 0;
        //中奖，减库存，入中奖纪录表
        if($rid!=0){
            //开启事务
            DB::beginTransaction();
            try{
                //if ($data['is_get'] > 1) { // 需要填写领取信息（排除谢谢惠顾）
                    //加入抽奖纪录表
                    $drawHistory = new AwardHistory();
                    $drawHistory->user_id = $user['id'];
                    $drawHistory->activity_id = $activity_id;
                    $drawHistory->award_id = $rid;
                    $drawHistory->goods_name = $data['goods_name'];
                    //$drawHistory->draw_time = date('Y-m-d H:i:s',time());
                    $drawHistory->status = $data['is_get'] == 1 ? 1: 2; // 1 已兑奖 2未兑奖
                    $drawHistory->data = json_encode($json_data);
                    $res = $drawHistory->save();
                    if (!$res) {
                        throw new \Exception('入抽奖历史表失败，请重新抽奖');
                    }
                    // 对应奖品库存-1
                    AwardGoods::where('id',$rid)->increment('un_stock',-1);
                    $history_id = $drawHistory->id;
                //}
                // 提交事务
                DB::commit();
            }catch (\Exception $e) {
                //事务回滚
                DB::rollback();
                return $this->error($e->getMessage());
            }
        }
        // 给用户加抽奖记录
        UserDrawRecord::insert([
            'user_id'       => $user['id'],
            'activity_id'   => $activity_id,
            'created_at'    => Carbon::now()
        ]);
        // 增加抽奖次数
        ActivityExtend::where('activity_id',$activity_id)->increment('total');
        $return = ['goods'=>$data,'history_id'=>$history_id];
        return $this->success('查询成功',$return);
    }

    /**
     * 用户中奖ID
     * @param array $arr 中奖几率
     * @param array $draw_num  必中次数
     * @param int $user_id
     * @param int $activity_id 活动ID
     * @return mixed
     */
    public function userDrawGoods($arr, $draw_num,$user_id,$activity_id){
        $rid=$this->_getRand($arr);  //中奖id
        // 查看中奖商品每个用户最大中奖数量
        $getNum = AwardGoods::getFieldValue($rid,'num');
        // 查看改用户是否中过该奖
        $userGetNum = AwardHistory::userGetNum($user_id,$rid);

//        if ($getNum != 0 && $userGetNum >= $getNum) {
//            $rid = $this->userDrawGoods($arr,$draw_num, $user_id,$activity_id);
//        }
        // 抽奖总次数
        $total_num = ActivityExtend::getTotalNum($activity_id);
        // 判断必中次数
        foreach ($draw_num as $key=>$item) {
            // 用户中奖次数
            $user_draw_num = AwardHistory::getDrawNum($key);
            if ($user_draw_num > 0) {
                return $rid;
                break;
            }
            // 中奖次数为0 + 没有达到中奖次数的 + 设置了次数的限制
            if ($item != 0 && $item > $total_num ) {
                if (ceil($item / 3) == $total_num) {
                    $rid = $key;
                }
            }
        }
        return $rid;
    }

    /**
     * 进行随机
     */
    private function _getRand($proArr){
        $result='';
        //概率数组的总概率精度
        $proSum=array_sum($proArr);
        //随机
        foreach ($proArr as $key=>$proCur){
            $randNum=mt_rand(1,$proSum);
            if($randNum <= $proCur){
                $result=$key;
                break;
            }else{
                $proSum-=$proCur;
            }
        }
        unset($proArr);
        return $result;
    }

    /**
     * 填写领取奖品信息
     * URL POST:/api/home/activity/signDrawInfo
     * @param Request $request
     * @param int history_id 中奖记录ID
     * @param int type 1、地址信息 2、手机
     * @param int goods_class_id 奖品ID
     * @param string mobile 手机
     * @param string username 联系人
     * @param string province 省
     * @param string city 市
     * @param string district 区
     * @param string address 详细地址
     * @return mixed
     */
    public function signDrawInfo(Request $request){
        $params = $request->only(['history_id','type','goods_class_id','mobile','username','province','city','district','address']);
        $type = isset($params['type']) ? $params['type'] : 1;
        $validator = Validator::make($params,[
            'history_id'            => ['required'],
            'mobile'                => ['required','regex:/^1[3456789]\d{9}$/'],
            'username'              => [$type==1?'required':'nullable'],
            //'province'              => [$type==1?'required':'nullable'],
            //'city'                  => [$type==1?'required':'nullable'],
            //'district'              => [$type==1?'required':'nullable'],
            'address'               => [$type==1?'required':'nullable'],
        ],[
            'history_id.required'   => '中奖记录ID是必须的',
            'mobile.required'       => '手机是必须的',
            'mobile.regex'          => '手机格式是必须的',
            'username.required'     => '用户名是必须的',
            //'province.required'     => '请选择省',
           // 'city.required'         => '请选择市',
            //'district.required'     => '请选择区',
            'address.required'      => '请输入详细地址'
        ]);
        if ($validator->fails()) {
            return $this->error($validator->errors()->first());
        }
        // 查看中奖信息是否存在
        $history = AwardHistory::find($params['history_id']);
        if (!$history) {
            return $this->error('中奖信息不存在');
        }
        // 减去相应的库存
        $awardGoods = AwardGoods::find($history->award_id);
        $award_name = '';
        if ($awardGoods->type == 2) {
            if (!array_key_exists('goods_class_id',$params) || empty($params['goods_class_id'])) {
                return $this->error('缺少奖品ID');
            }
            $award_name = AwardGoodsClass::getField(array('id'=>$params['goods_class_id']),'name');
            AwardGoodsClass::where('id',$params['goods_class_id'])->increment('un_stock',-1);
        }
        // 地址信息
        if ($type == 1) {
            $data = [
                'mobile'        => $params['mobile'],
                'award_name'    => $award_name,
                'username'      => isset($params['username']) ? $params['username'] : '',
//                'province'      => isset($params['province']) ? $params['province'] : '',
//                'province_str'  => isset($params['province']) ? Region::getByIdName($params['province']) : '',
//                'city'          => isset($params['city']) ? $params['city'] : '',
//                'city_str'      => isset($params['city']) ? Region::getByIdName($params['city']) : '',
//                'district'      => isset($params['district']) ? $params['district'] : '',
//                'district_str'  => isset($params['district']) ? Region::getByIdName($params['district']) : '',
                'address'       => isset($params['address']) ? $params['address'] : ''
            ];
        }else{
            $data = [
                'mobile'    => $params['mobile']
            ];
        }
        $where = [];
        $where[] = ['id',$params['history_id']];
        $filed = [
            'draw_data'=>json_encode($data),
            'award_name'=> $award_name,
            'mobile'   => $params['mobile'],
            'username' => isset($params['username']) ? $params['username'] : '',
//            'province' => isset($params['province']) ? $params['province'] : '',
//            'city'     => isset($params['city']) ? $params['city'] : '',
//            'district' => isset($params['district']) ? $params['district'] : '',
            'address'  => isset($params['address']) ? $params['address'] : ''
        ];
        $result = AwardHistory::modify($where,$filed);
        if ($result === false) {
            return $this->error('操作失败');
        }
        return $this->success('操作成功');
    }

    /**
     * 中奖用户列表
     * URL POST:/api/home/activity/winPrizeList
     * @param Request $request
     * @param int activity_id 活动ID
     * @param int page 页码
     * @param int limit 每页显示条数
     * @return mixed
     */
    public function winPrizeList(Request $request){
        $params = $request->only(['activity_id','page','limit']);
        //$params['activity_id'] = 1; // 目前只有一个活动
//        if (!array_key_exists('activity_id',$params) || empty($params['activity_id'])) {
//            return $this->error('缺少活动ID');
//        }
//        $params['where'][] = ['activity_id',$params['activity_id']];
        $params['orderBy'] = ['created_at desc'];
        // 用户
        $params['with'][] = 'user:id,name,mobile';
        // 奖品
        $params['with'][] = 'goods:id,name';
        // 活动信息
        $params['with'][] = 'activity:id,name';
        $params['whereHas'][] = ['goods',function($query){
            $query->where('is_get','>',1);
        }];
        $data = AwardHistory::listByWhere($params);
        return $this->success('查询成功',$data);
    }

    /**
     * 投诉建议
     * URL POST:/api/home/activity/advise
     * @param Request $request
     * @param string content 投诉建议内容
     * @return mixed
     */
    public function advise(Request $request){
        $params = $request->only(['content']);
        if (!array_key_exists('content',$params) || empty($params['content'])) {
            return $this->error('请输入投诉建议内容');
        }
        // 用户信息
        $user = $this->userModel();
        $result = Advise::insert([
            'user_id'       => $user['id'],
            'content'       => $params['content'],
            'created_at'    => Carbon::now(),
            'updated_at'    => Carbon::now()
        ]);
        if ($result === false) {
            return $this->error('添加失败');
        }
        return $this->success('添加成功');
    }
}